<!--
 * @Description: 表单编辑页面
 * @Author: HuiSir<https://gitee.com/huisir001>
 * @Date: 2025-06-22 15:07:52
 * @LastEditTime: 2025-09-28 18:03:35
-->
<template>
  <div class="form-set-page">
    <h3>{{ title }}</h3>
    <fy-form
      ref="myForm"
      class="my-form"
      v-loading="loading"
      v-model="formData"
      :inputWidth="inputWidth"
      :showBtns="false"
      :options="formOptions"
      :inline="false"
      :labelWidth="labelWidth"
      @upload:change="bindUploadChange"
    >
      <template
        v-for="item in formOptions.filter((o) => o.slot)"
        :key="item.key"
        v-slot:[item.slot]
      >
        <slot :name="item.slot" :val="formData" :options="formOptions" />
      </template>
    </fy-form>
    <slot />
    <fy-page-btn
      align="left"
      :offset="10"
      :loading="submitLoading"
      :label="buttonName"
      @submit="handleSubmit"
    >
      <template v-if="$slots.btnLeft" #left>
        <slot name="btnLeft" />
      </template>
      <template v-if="$slots.btnRight" #right>
        <slot name="btnRight" />
      </template>
    </fy-page-btn>
  </div>
</template>

<script lang="ts" setup>
import { PropType, ref } from "vue";
import {
  IFormOption,
  SubmitCallbacks,
  UploadEventParams,
  UploadChangeForm,
} from "../types";

// 组件名称（必要）
defineOptions({ name: "FyFormPage" });

// 表单数据
const formData = defineModel<Record<string, unknown>>({ required: true });

/**
 * 表单项配置选项,允许动态修改
 */
const formOptions = defineModel("options", {
  type: Array as PropType<IFormOption[]>,
  required: true,
  default: () => [],
});

defineProps({
  /**
   * 标题
   */
  title: {
    type: String,
    required: true,
    default: "设置",
  },
  /**
   * 按钮名称
   */
  buttonName: {
    type: String,
    default: "保存",
  },
  /**
   * loading
   */
  loading: {
    type: Boolean,
    default: false,
  },
  /**
   * label宽度
   */
  labelWidth: {
    type: [String, Number],
    require: false,
    default: 80,
  },
  inputWidth: {
    type: [String, Number],
    require: false,
    default: 500,
  },
});

// 表单对象
const myForm = ref();

// emit
const emit = defineEmits<{
  // 元组语法：明确参数名称和类型
  submit: [
    callbacks: {
      closeLoading: SubmitCallbacks["closeLoading"];
      uploadSubmit: SubmitCallbacks["uploadSubmit"];
      validate: SubmitCallbacks["validate"];
    }
  ];
  "upload:change": [uploadParams: UploadEventParams, form: UploadChangeForm];
}>();

const submitLoading = ref(false);

// 表单验证
const validate = async () => {
  const validateRes = await myForm.value.validate().catch(() => {
    submitLoading.value = false;
  });

  if (!validateRes) {
    submitLoading.value = false;
  }

  return validateRes;
};

// 提交表单
const handleSubmit = () => {
  submitLoading.value = true;
  emit("submit", {
    validate,
    closeLoading: () => (submitLoading.value = false),
    uploadSubmit: myForm.value.uploadSubmit,
  });
};

/**
 * 文件更新事件
 */
const bindUploadChange = (uploadParams: UploadEventParams) => {
  emit("upload:change", uploadParams, {
    data: formData,
    options: formOptions,
  });
};
</script>

<style scoped lang="scss">
.form-set-page {
  margin: 0 20px 20px 20px;
  h3 {
    position: sticky;
    top: 0;
    background: #fff;
    width: 100%;
    z-index: 2;
    padding: 20px 0 15px 0;
  }
  .my-form {
    margin-top: 15px;
    max-width: 100%;
  }
}
@media screen and (max-width: 590px) {
  .form-set-page {
    margin: 0 15px 20px 15px;
    :deep(.el-form-item) {
      display: block;
      margin-bottom: 20px;
    }
  }
}
</style>
